﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.IO.Ports;
using System.Threading;
namespace GPRSLib
{
    class gmsClass
    {
        public static AutoResetEvent waitThread;
        public static AutoResetEvent readNow = new AutoResetEvent(false);
        string input="";
        #region Open and Close Ports
        //Open Port
        public SerialPort OpenPort(string p_strPortName, int p_uBaudRate, int p_uDataBits, int p_uReadTimeout, int p_uWriteTimeout)
        {
            waitThread = new AutoResetEvent(false);
            SerialPort port = new SerialPort();
           
            try
            {
                
                port.PortName = p_strPortName;                 //COM5
                port.BaudRate = p_uBaudRate;                   //9600
                port.DataBits = p_uDataBits;                   //8
                port.StopBits = StopBits.One;                  //1
                port.Parity = Parity.None;                     //None
                port.ReadTimeout = p_uReadTimeout;             //300
                port.WriteTimeout = p_uWriteTimeout;           //300
                port.Encoding = Encoding.GetEncoding("iso-8859-1");
                port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
                
                port.Open();
                
                port.DtrEnable = true;
                port.RtsEnable = true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return port;
        }

        //Close Port
        public void ClosePort(SerialPort port)
        {
            try
            {
                port.Close();
                port.DataReceived -= new SerialDataReceivedEventHandler(port_DataReceived);
                port = null;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion
        //Receive data from port
        public void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            try
            {

                SerialPort p = (SerialPort)sender;
                while (true)
                {
                    if (e.EventType == SerialData.Chars)
                    {
                        input += p.ReadExisting();
                    }
                    if(input == "" || input.EndsWith("\r\nERROR\r\n") || input.EndsWith("\r\nOK\r\n"))
                    {
                        break;
                    }
               }
                waitThread.Set();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        //Execute AT Command
        public string ExecuteATCommand(SerialPort port, string command, int responseTimeout, string errorMessage)
        {
            try
            {
                string result = "";
                port.DiscardOutBuffer();
                port.DiscardInBuffer();
                waitThread.Reset();
                port.Write(command + "\r\n");        
                waitThread.WaitOne(4000);

                System.Diagnostics.EventLog.WriteEntry("sms", input);
                if ((input.Length == 0) || input.EndsWith("\r\nERROR\r\n") || (!input.EndsWith("\r\nOK\r\n")))
                    throw new Exception(errorMessage);
                else
                {
                    result = input;
                    input = "";
                }
                return result;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public List<ShortMessage> ReadSMS(SerialPort port, string p_strCommand)
        {

            // Set up the phone and read the messages
            List<ShortMessage> messages = null;
            try
            {

                #region Execute Command
                // Check connection
                ExecuteATCommand(port, "AT", 300, "No phone connected");
                // Use message format "Text mode"
                ExecuteATCommand(port, "AT+CMGF=1", 300, "Failed to set message format.");
                // Select SIM storage
                //ExecuteATCommand(port, "AT+CPMS=\"SM\"", 300, "Failed to select message storage.");
                // Read the messages
                string input = ExecuteATCommand(port, p_strCommand, 5000, "Failed to read the messages.");
                #endregion

                #region Parse messages
                messages = ParseMessages(input);
                #endregion

            }
            catch (Exception ex)
            {
                throw ex;
            }

            if (messages != null)
                return messages;
            else
                return null;

        }
        public List<ShortMessage> ParseMessages(string input)
        {
            List<ShortMessage> messages = new List<ShortMessage>();
            try
            {
                Regex r = new Regex(@"\+CMGL: (\d+),""(.+)"",""(.+)"",(.*),""(.+)""\r\n(.+)\r\n");
                Match m = r.Match(input);
                while (m.Success)
                {
                    ShortMessage msg = new ShortMessage();
                    //msg.Index = int.Parse(m.Groups[1].Value);
                    msg.Index = m.Groups[1].Value;
                    msg.Status = m.Groups[2].Value;
                    msg.Sender = m.Groups[3].Value;
                    msg.Alphabet = m.Groups[4].Value;
                    msg.Sent = m.Groups[5].Value;
                    msg.Message = m.Groups[6].Value;
                    messages.Add(msg);

                    m = m.NextMatch();
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }
            return messages;
        }
        public bool DeleteMsg(SerialPort port, string p_strCommand)
        {
            bool isDeleted = false;
            try
            {

                #region Execute Command
                string recievedData = ExecuteATCommand(port, "AT", 300, "No phone connected");
                recievedData = ExecuteATCommand(port, "AT+CMGF=1", 300, "Failed to set message format.");
                String command = p_strCommand;
                recievedData = ExecuteATCommand(port, command, 300, "Failed to delete message");
                #endregion

                if (recievedData.EndsWith("\r\nOK\r\n"))
                {
                    isDeleted = true;
                }
                if (recievedData.Contains("ERROR"))
                {
                    isDeleted = false;
                }
                return isDeleted;
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
        
        public bool sendMsg(SerialPort port, string PhoneNumber, string Message)
        {
            bool isSend = false;

            try
            {
                string recievedData = "";
               // string recievedData = ExecuteATCommand(port, "AT", 300, "No phone connected");
               // recievedData = ExecuteATCommand(port, "AT+CMGF=1", 300, "Failed to set message format.");
                string command = "AT+CMGS=\"" + PhoneNumber + "\"" + "\r\n" + Message + char.ConvertFromUtf32(26);
                recievedData = ExecuteATCommand(port, command, 300, "Failed to sendSMS phoneNo");
                //add -> after message
    
                if (recievedData.EndsWith("\r\nOK\r\n"))
                {
                    isSend = true;
                }
                else if (recievedData.Contains("ERROR") || recievedData == "")
                {
                    isSend = false;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
            return isSend;
        }
        
    }
}
